﻿namespace Beetle
{
    using Smark.Core;
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Text;
    using System.Threading;

    public class TcpChannel : IDisposable
    {
        internal const string _field_a = "<Exponent>{0}</Exponent>";
        private bool _field_aa;
        internal SendMessageCompletedArgs _field_ab = new SendMessageCompletedArgs();
        internal bool _field_ac;
        internal bool _field_ad;
        internal bool _field_ae;
        [CompilerGenerated]
        private ChannelStatus _field_af;
        [CompilerGenerated]
        private DateTime _field_ag;
        [CompilerGenerated]
        private object _field_ah;
        [CompilerGenerated]
        private Encoding _field_ai;
        [CompilerGenerated]
        private long _field_aj;
        [CompilerGenerated]
        private IPEndPoint _field_ak;
        [CompilerGenerated]
        private string _field_al;
        private static long _field_b = 0L;
        internal bool _field_c;
        internal int _field_d = -1;
        internal int _field_e;
        internal TcpServer _field_f;
        private KeyValueCollection<object> _field_g = new KeyValueCollection<object>();
        internal Beetle.Package _field_h;
        private EventChannelError _field_i;
        private EventChannelDisposed _field_j;
        internal static string _field_k = "V/r2I2CpRaI=";
        internal Class_aa _field_l;
        internal Class_ag _field_m;
        internal Class_ag _field_n;
        internal Class_ah _field_o;
        internal Class_ah _field_p;
        internal Class_ah _field_q;
        internal ChannelReceiveEventArgs _field_r = new ChannelReceiveEventArgs();
        private System.Net.Sockets.Socket _field_s;
        private bool _field_t;
        private Class_p _field_u = new Class_p();
        private Class_ac _field_v = new Class_ac();
        private BufferWriter _field_w;
        internal Queue<IMessage> _field_x = new Queue<IMessage>(0x100);
        internal Class_u.Class_u_a _field_y;
        private IMessage _field_z;
        public string CloseStatus = "";
        public EventDataReceive DataReceive;
        public bool EnabledSendCompeletedEvent;
        public bool EnabledVariant;
        public EventMessageWriter MessageWrited;
        public EventMessageWriter MessageWriting;
        public long ReceiveBytes;
        public long SendBytes;
        public EventSendMessageCompleted SendMessageCompleted;
        public bool SynSend;
        public int TickCount = Environment.TickCount;

        public event EventChannelDisposed ChannelDisposed
        {
            add
            {
                EventChannelDisposed disposed2;
                EventChannelDisposed disposed = this._field_j;
                do
                {
                    disposed2 = disposed;
                    EventChannelDisposed disposed3 = (EventChannelDisposed) Delegate.Combine(disposed2, value);
                    disposed = Interlocked.CompareExchange<EventChannelDisposed>(ref this._field_j, disposed3, disposed2);
                }
                while (disposed != disposed2);
            }
            remove
            {
                EventChannelDisposed disposed2;
                EventChannelDisposed disposed = this._field_j;
                do
                {
                    disposed2 = disposed;
                    EventChannelDisposed disposed3 = (EventChannelDisposed) Delegate.Remove(disposed2, value);
                    disposed = Interlocked.CompareExchange<EventChannelDisposed>(ref this._field_j, disposed3, disposed2);
                }
                while (disposed != disposed2);
            }
        }

        public event EventChannelError ChannelError
        {
            add
            {
                EventChannelError error2;
                EventChannelError error = this._field_i;
                do
                {
                    error2 = error;
                    EventChannelError error3 = (EventChannelError) Delegate.Combine(error2, value);
                    error = Interlocked.CompareExchange<EventChannelError>(ref this._field_i, error3, error2);
                }
                while (error != error2);
            }
            remove
            {
                EventChannelError error2;
                EventChannelError error = this._field_i;
                do
                {
                    error2 = error;
                    EventChannelError error3 = (EventChannelError) Delegate.Remove(error2, value);
                    error = Interlocked.CompareExchange<EventChannelError>(ref this._field_i, error3, error2);
                }
                while (error != error2);
            }
        }

        public TcpChannel(System.Net.Sockets.Socket socket)
        {
            if (!TcpUtils._field_a)
            {
                throw NetTcpException.NotInitialize();
            }
            this.Coding = Encoding.UTF8;
            this._field_s = socket;
            this._field_m = Class_ag.b();
            this.CreateTime = DateTime.Now;
            this._field_n = TcpUtils._field_b;
            this._field_o = TcpUtils.b();
            this._field_p = TcpUtils.d();
            this._field_q = TcpUtils.c();
            a(this);
            this.EndPoint=((IPEndPoint) socket.RemoteEndPoint);
            this._field_w = new BufferWriter(this.Coding, this._field_n);
            this._field_r.Channel = this;
            this._field_l = Class_aa.f();
            this._field_c = Class_b._field_c;
        }

        private void a()
        {
            if (this._field_f != null)
            {
                this._field_ac = this._field_f._field_o.Count > Class_ag._field_a;
            }
        }

        private void a(BufferWriter A_0)
        {
            Class_b _b = null;
            int offset = 0;
            while (A_0._field_b.Count > 0)
            {
                _b = A_0.d();
                if (_b != null)
                {
                    try
                    {
                        offset = 0;
                        while (offset < _b._field_h)
                        {
                            if (this._field_ae)
                            {
                                break;
                            }
                            int num2 = this.Socket.Send(_b._field_e, offset, _b._field_h - offset, SocketFlags.None);
                            offset += num2;
                            if (TcpUtils.Statistics)
                            {
                                lock (TcpUtils._field_d)
                                {
                                    TcpUtils.SendBytes += num2;
                                    this.SendBytes += num2;
                                    TcpUtils.SendDataIO += 1L;
                                    continue;
                                }
                            }
                        }
                        continue;
                    }
                    finally
                    {
                        _b.Dispose();
                    }
                }
            }
            this.a(false);
            this.Send(null);
        }

        internal void a(ChannelReceiveEventArgs A_0)
        {
            this.OnDataReceive(A_0);
        }

        private bool a(IMessage A_0)
        {
            if (((this.Socket == null) || this._field_ae) || this._field_ac)
            {
                if (A_0 is ICounter)
                {
                    ((ICounter) A_0).Reduce();
                }
                return false;
            }
            lock (this._field_x)
            {
                if (A_0 != null)
                {
                    this._field_x.Enqueue(A_0);
                }
                if (((this._field_x.Count > 0) && !this._field_t) && !this._field_ae)
                {
                    this.a(true);
                    this._field_u._field_f = this;
                    this._field_p.a((Class_ad) this._field_u);
                }
                return true;
            }
        }

        private static void a(TcpChannel A_0)
        {
            lock (typeof(TcpChannel))
            {
                A_0["_data"] = 0xff;
                _field_b += 1L;
                A_0.ClientID=(_field_b);
            }
        }

        internal void a(bool A_0)
        {
            this._field_t = A_0;
        }

        internal void b()
        {
            this._field_ad = true;
            TcpServer.ReleaseSocket(this.Socket);
            this._field_s = null;
            if (this._field_w != null)
            {
                this._field_w.Dispose();
            }
            this._field_n = null;
            if (this._field_h != null)
            {
                this._field_h.Dispose();
                this._field_h = null;
            }
            try
            {
                while (this._field_x.Count > 0)
                {
                    IMessage message = this._field_x.Dequeue();
                    if (message is ICounter)
                    {
                        ((ICounter) message).Reduce();
                    }
                }
            }
            catch
            {
            }
            this._field_v._field_f = null;
            this._field_v = null;
            this._field_u._field_f = null;
            this._field_u = null;
            this.MessageWriting = null;
            this._field_y = null;
            this._field_g.Clear();
            this._field_n = null;
            this._field_w = null;
            this._field_r.Channel = null;
            this._field_r = null;
            this.Server=((TcpServer) null);
            this.Tag = null;
            this._field_ab.Channel = null;
            this._field_ab = null;
        }

        internal void b(BufferWriter A_0)
        {
            Class_b _b = null;
            try
            {
                if (this.SynSend)
                {
                    this.a(A_0);
                }
                else
                {
                    _b = A_0.c();
                    if (_b != null)
                    {
                        if (!this._field_ae)
                        {
                            Class_a e = _b.b();
                            e.a(this);
                            e.UserToken = A_0;
                            if (!this.Socket.SendAsync(e))
                            {
                                e.a(e);
                            }
                        }
                        else
                        {
                            _b.Dispose();
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                if (_b != null)
                {
                    _b.Dispose();
                }
                throw exception;
            }
        }

        public void BeginReceive()
        {
            if (TcpUtils.UseReceiveAsyncQueue)
            {
                this._field_v._field_f = this;
                this._field_q.a((Class_ad) this._field_v);
            }
            else
            {
                this.c();
            }
        }

        internal void c()
        {
            if (!this._field_ae && this._field_l._field_a)
            {
                Class_a e = TcpUtils._field_e.d();
                e.a(this);
                try
                {
                    this._field_aa = this.Socket.ReceiveAsync(e);
                    if (!this._field_aa)
                    {
                        e.b(e);
                    }
                }
                catch (Exception exception)
                {
                    e.d();
                    ChannelErrorEventArgs args = new ChannelErrorEventArgs {
                        Channel = this,
                        Exception = exception
                    };
                    this.CallChannelError(args);
                }
            }
        }

        public void CallChannelError(ChannelErrorEventArgs e)
        {
            try
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(this.OnChannelError), e);
            }
            catch
            {
            }
        }

        internal void d()
        {
            if ((this.Socket != null) && !this._field_ae)
            {
                lock (this._field_x)
                {
                    if (this._field_x.Count == 0)
                    {
                        return;
                    }
                    if (this.EnabledSendCompeletedEvent && (this._field_w._field_i.Count > 0))
                    {
                        this._field_w._field_i.Clear();
                    }
                    this._field_w.Reset();
                    this._field_w.EnabledVariant = this.EnabledVariant;
                    while (this._field_x.Count > 0)
                    {
                        this._field_z = this._field_x.Dequeue();
                        if (this.EnabledSendCompeletedEvent)
                        {
                            this._field_w._field_i.Add(this._field_z);
                        }
                        if (this.MessageWriting == null)
                        {
                            this._field_z.Save(this._field_w);
                        }
                        else
                        {
                            this.MessageWriting(this._field_z, this._field_w);
                            lock (TcpUtils._field_j)
                            {
                                TcpUtils.SendMessages += 1L;
                            }
                            if (this.MessageWrited != null)
                            {
                                this.MessageWrited(this._field_z, this._field_w);
                            }
                        }
                        if (this._field_z is ICounter)
                        {
                            ((ICounter) this._field_z).Reduce();
                        }
                    }
                }
                this.b(this._field_w);
            }
        }

        public void Dispose()
        {
            lock (this)
            {
                if (!this._field_ae)
                {
                    this._field_ae = true;
                    ChannelDisposedEventArgs e = new ChannelDisposedEventArgs();
                    e.Message=(this._field_x);
                    e.Clean = true;
                    e.Channel = this;
                    try
                    {
                        this.OnChannelDisposed(e);
                    }
                    catch
                    {
                    }
                    if (e.Clean)
                    {
                        e.Channel = null;
                        this.b();
                    }
                    else
                    {
                        ChannelDisposedQueue.DisposedQueue.Add(e);
                    }
                }
            }
        }

        internal void e()
        {
            try
            {
                if (this.SendMessageCompleted != null)
                {
                    this._field_ab.Channel = this;
                    this.SendMessageCompleted(this, this._field_ab);
                }
            }
            catch
            {
            }
        }

        protected virtual void OnChannelDisposed(ChannelDisposedEventArgs e)
        {
            if (this._field_j != null)
            {
                this._field_j(this, e);
            }
        }

        protected virtual void OnChannelError(object e)
        {
            ChannelErrorEventArgs args = (ChannelErrorEventArgs) e;
            try
            {
                if ((this._field_i != null) && !this._field_ae)
                {
                    this._field_i(this, args);
                }
            }
            catch
            {
            }
            try
            {
                if (((args.Exception is SocketException) || (args.Exception is ObjectDisposedException)) || (args.Exception is NetTcpException))
                {
                    this.CloseStatus = "Socket Disposed!";
                    this.Dispose();
                }
            }
            catch
            {
            }
        }

        protected virtual void OnDataReceive(ChannelReceiveEventArgs e)
        {
            if ((this.DataReceive != null) && !this._field_ad)
            {
                this.DataReceive(this, e);
            }
        }

        public bool Send(object message)
        {
            if ((this.Package != null) && (message != null))
            {
                return this.a((IMessage) this.Package.WriteCast(message));
            }
            return this.a((IMessage) message);
        }

        public Beetle.Package SetPackage<T>() where T: Beetle.Package
        {
            return this.SetPackage<T>(null);
        }

        public Beetle.Package SetPackage<T>(ChannelController controller) where T: Beetle.Package
        {
            this._field_h = (Beetle.Package) Activator.CreateInstance(typeof(T), new object[] { this });
            if (controller != null)
            {
                controller.Register(this._field_h);
            }
            return this._field_h;
        }

        public long ClientID
        {
            [CompilerGenerated]
            get
            {
                return this._field_aj;
            }
            [CompilerGenerated]
            internal set
            {
                this._field_aj = value;
            }
        }

        public Encoding Coding
        {
            [CompilerGenerated]
            get
            {
                return this._field_ai;
            }
            [CompilerGenerated]
            set
            {
                this._field_ai = value;
            }
        }

        public DateTime CreateTime
        {
            [CompilerGenerated]
            get
            {
                return this._field_ag;
            }
            [CompilerGenerated]
            set
            {
                this._field_ag = value;
            }
        }

        public IPEndPoint EndPoint
        {
            [CompilerGenerated]
            get
            {
                return this._field_ak;
            }
            [CompilerGenerated]
            internal set
            {
                this._field_ak = value;
            }
        }

        public bool IsDisposed
        {
            get
            {
                return this._field_ae;
            }
        }

        public object this[string name]
        {
            get
            {
                return this._field_g[name];
            }
            set
            {
                this._field_g[name] = value;
            }
        }

        public string Name
        {
            [CompilerGenerated]
            get
            {
                return this._field_al;
            }
            [CompilerGenerated]
            set
            {
                this._field_al = value;
            }
        }

        public Beetle.Package Package
        {
            get
            {
                return this._field_h;
            }
        }

        public KeyValueCollection<object> Properties
        {
            get
            {
                return this._field_g;
            }
        }

        public int SendQueues
        {
            get
            {
                return this._field_x.Count;
            }
        }

        public TcpServer Server
        {
            get
            {
                return this._field_f;
            }
            internal set
            {
                this._field_f = value;
                this.a();
            }
        }

        public System.Net.Sockets.Socket Socket
        {
            get
            {
                return this._field_s;
            }
        }

        public ChannelStatus Status
        {
            [CompilerGenerated]
            get
            {
                return this._field_af;
            }
            [CompilerGenerated]
            set
            {
                this._field_af = value;
            }
        }

        public object Tag
        {
            [CompilerGenerated]
            get
            {
                return this._field_ah;
            }
            [CompilerGenerated]
            set
            {
                this._field_ah = value;
            }
        }
    }
}

